#include "ComponentRandomFeedBehavior.h"
#include "Components/ComponentCreature.h"
#include "Components/ComponentBody.h"
#include "Components/ComponentCreatureSounds.h"
#include "Components/ComponentCreatureModel.h"

#include "ComponentPathfinding.h"
#include "Subsystems/SubsystemTerrain.h"
#include "GameRandom.hpp"
#include "Engine/MathUtils.hpp"
#include "Log.h"

#include "GameSingleton.h"
#include "GameRegistry.hpp"
#include "GameThreadPool.hpp"

#include <iostream>

namespace PocketSurvival
{

    // ************** 【状态机】 **************

    ComponentRandomFeedBehavior::StateMachine::StateMachine(ComponentRandomFeedBehavior *feedBehavior) : m_feedBehavior(feedBehavior), EasyMachine(MachineState::Inactive)
    {
        enter();
    }

    void ComponentRandomFeedBehavior::StateMachine::enter()
    {
        switch (m_currentState)
        {
        case MachineState::Inactive:
            m_feedBehavior->m_importanceLevel = GameSingleton::gameRandom->getFloat(0.0f, 1.0f);
            break;
        case MachineState::Move:
            MACHINE_DELEGATE()
            {
                Vector3 value;
                if (m_feedBehavior->m_feedPosition != FastVector3::Zero)
                {
                    value = m_feedBehavior->m_feedPosition;
                }
                else
                {
                    Vector3 position;
                    m_feedBehavior->componentCreature->componentBody->getPosition(position);

                    Vector3 forward = m_feedBehavior->componentCreature->componentBody->getMatrix().getForward();
                    float num4 = (GameSingleton::gameRandom->getFloat(0.0f, 1.0f) < 0.2f) ? 5.0f : 1.5f;
                    value = position + num4 * forward + 0.5f * num4 * Vector3(GameSingleton::gameRandom->getFloat(-1.0f, 1.0f), 0.0f, GameSingleton::gameRandom->getFloat(-1.0f, 1.0f));
                }
                value.posY = m_feedBehavior->subsystemTerrain->getTopHeight(Terrain::ToCell(value.posX), Terrain::ToCell(value.posZ)) + 1;
                m_feedBehavior->componentPathfinding->setDestination(value, GameSingleton::gameRandom->getFloat(0.25f, 0.33f), 1.0f, 0, false, true, false, nullptr);
            }
            break;
        case MachineState::LookAround:
            m_feedBehavior->m_waitTime = GameSingleton::gameRandom->getFloat(1.0f, 2.0f);
            break;
        case MachineState::Feed:
            m_feedBehavior->m_feedTime = GameSingleton::gameRandom->getFloat(4.0f, 6.0f);
            break;
        }
    }

    void ComponentRandomFeedBehavior::StateMachine::update(float dt)
    {
        switch (m_currentState)
        {
        case MachineState::Inactive:
            MACHINE_DELEGATE()
            {
                if (GameSingleton::gameRandom->getFloat(0.0f, 1.0f) < 0.05 * dt)
                {
                    m_feedBehavior->m_importanceLevel = GameSingleton::gameRandom->getFloat(1.0f, 3.0f);
                }
                if (m_feedBehavior->isActive())
                {
                    changeTo(MachineState::Move);
                }
            }
            break;
        case MachineState::Move:
            MACHINE_DELEGATE()
            {
                if (m_feedBehavior->componentPathfinding->destination == FastVector3::Zero)
                {
                    float num3 = GameSingleton::gameRandom->getFloat(0.0f, 1.0f);
                    if (num3 < 0.33f)
                    {
                        changeTo(MachineState::Inactive);
                    }
                    else if (num3 < 0.66f)
                    {
                        changeTo(MachineState::LookAround);
                    }
                    else
                    {
                        changeTo(MachineState::Feed);
                    }
                }
                else if (m_feedBehavior->isActive() == false || m_feedBehavior->componentPathfinding->isStuck)
                {
                    changeTo(MachineState::Inactive);
                }
            }
            break;
        case MachineState::LookAround:
            MACHINE_DELEGATE()
            {
                m_feedBehavior->componentCreature->componentCreatureModel->lookRandomOrder = true;
                m_feedBehavior->m_waitTime -= dt;
                if (m_feedBehavior->m_waitTime <= 0.0f)
                {
                    float num2 = GameSingleton::gameRandom->getFloat(0.0f, 1.0f);
                    if (num2 < 0.25f)
                    {
                        changeTo(MachineState::Inactive);
                    }
                    if (num2 < 0.5f)
                    {
                        changeTo(MachineState::LookAround);
                    }
                    else if (num2 < 0.75f)
                    {
                        changeTo(MachineState::Move);
                        if (GameSingleton::gameRandom->getFloat(0.0f, 1.0f) < 0.1f * dt)
                        {
                            // 播放声音
                        }
                    }
                    else
                    {
                        changeTo(MachineState::Feed);
                    }
                }
                if (m_feedBehavior->isActive() == false)
                {
                    changeTo(MachineState::Inactive);
                }
            }
            break;
        case MachineState::Feed:
            MACHINE_DELEGATE()
            {
                m_feedBehavior->m_feedTime -= dt;
                if (m_feedBehavior->componentCreature->componentBody->standingOnValue != 0)
                {
                    m_feedBehavior->setIsFeed(true);
                    if (GameSingleton::gameRandom->getFloat(0.0f, 1.0f) < 0.1f * dt)
                    {
                        // 播放声音
                    }
                    if (GameSingleton::gameRandom->getFloat(0.0f, 1.0f) < 1.5f * dt)
                    {
                        // 播放声音
                    }
                }
                if (m_feedBehavior->m_feedTime <= 0.0f)
                {
                    if (m_feedBehavior->m_autoFeed)
                    {
                        float num = GameSingleton::gameRandom->getFloat(0.0f, 1.0f);
                        if (num < 0.33f)
                        {
                            changeTo(MachineState::Inactive);
                        }
                        if (num < 0.66f)
                        {
                            changeTo(MachineState::Move);
                        }
                        else
                        {
                            changeTo(MachineState::LookAround);
                        }
                    }
                    else
                    {
                        m_feedBehavior->m_importanceLevel = 0.0f;
                    }
                }
                if (m_feedBehavior->isActive() == false)
                {
                    changeTo(MachineState::Inactive);
                }
            }
            break;
        }
    }

    void ComponentRandomFeedBehavior::StateMachine::leave()
    {
        switch (m_currentState)
        {
        case MachineState::Inactive:
            break;
        case MachineState::Move:
            m_feedBehavior->m_feedPosition = FastVector3::Zero;
            break;
        case MachineState::LookAround:
            break;
        case MachineState::Feed:
            m_feedBehavior->setIsFeed(false);
            break;
        }
    }

    // **************************************



    ComponentRandomFeedBehavior::~ComponentRandomFeedBehavior()
    {
        delete m_stateMachine;
    }

    float ComponentRandomFeedBehavior::getImportanceLevel()
    {
        return m_importanceLevel;
    }
    bool ComponentRandomFeedBehavior::getIsFeed()
    {
        return m_isFeed;
    }
    void ComponentRandomFeedBehavior::setIsFeed(bool feed)
    {
        if (m_isFeed != feed)
        {
            m_isFeed = feed;
            // 发送数据包 待完成...
        }
    }
    void ComponentRandomFeedBehavior::feed(const Vector3& feedPosition)
    {
        m_importanceLevel = 5.0f;
        m_feedPosition = feedPosition;
    }


    void ComponentRandomFeedBehavior::update(float dt)
    {
        m_stateMachine->update(dt);
    }


    static const std::string componentName = "FeedBehavior";
    const std::string &ComponentRandomFeedBehavior::getName() const
    {
        return componentName;
    }
    const std::string &ComponentRandomFeedBehavior::GetName()
    {
        return componentName;
    }
    void ComponentRandomFeedBehavior::load(const nlohmann::json &jsonData)
    {
        componentCreature    = GameSingleton::gameRegistry->get<ComponentCreature *>(entity);
        componentPathfinding = GameSingleton::gameRegistry->get<ComponentPathfinding *>(entity);

        subsystemTerrain = GameSingleton::singletonPtr->getSingleton<SubsystemTerrain>();

        m_stateMachine = new StateMachine(this);
    }

}
